package com.hn.framework.config;

import com.alibaba.fastjson.JSON;
import com.hn.framework.aspectj.lang.annotation.NotAuth;
import com.hn.common.constant.RedisConstant;
import com.hn.common.utils.SecurityUtils;
import com.hn.common.enums.ResultCode;
import com.hn.framework.redis.RedisCache;
import com.hn.framework.web.domain.AjaxResult;
import com.hn.common.utils.CommonUtils;
import com.hn.common.utils.IpUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 登陆拦截
 */
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {

    private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

    @Autowired
    private RedisCache redisCache;

    @Value("${spring.profiles.active}")
    private String env;

    private List<String> unfilteredUrl = new ArrayList<>();

    @PostConstruct
    private void init(){
        // 不过滤的一些swagger url
        unfilteredUrl.add("/swagger-resources/configuration/ui");
        unfilteredUrl.add("/swagger-ui");
        unfilteredUrl.add("/swagger-resources/configuration/security");
        unfilteredUrl.add("/swagger-resources");
        unfilteredUrl.add("/error");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        // SpringMVC 的handler到底是什么呢？它是对Controller的Bean本身和请求Method的包装。
        if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
            return true;
        }

        //如果不是生产环境放开swagger
        if (!"pro".equals(env)){
            // 不过滤的url
            if (unfilteredUrl.contains(request.getServletPath())){
                return true;
            }
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        Class<?> clazz = method.getDeclaringClass();
        // 如果类或者方法上 包含注解NotAuth 就是不需要校验
        if (clazz.isAnnotationPresent(NotAuth.class) || method.isAnnotationPresent(NotAuth.class)) {
            return true;
        }

        // 获取客户端的token
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {
            return authFail(request, response);
        }

        // 从token中获取用户id
        Integer userId = redisCache.getCacheObject(RedisConstant.USER_TOKEN + token);
        if (userId == null) {
            return authFail(request, response);
        }

        // 将用户id存入request
        SecurityUtils.setUserId(userId);

        return true;
    }

    private boolean authFail(HttpServletRequest request, HttpServletResponse response) {
        logger.warn("登录认证失败，请求接口：{}，请求IP：{}，请求参数：{}",
                request.getRequestURI(), IpUtils.getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
        AjaxResult result = AjaxResult.error(ResultCode.UNAUTHORIZED.code(),"未登录");
        CommonUtils.responseResult(response, result);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
    }

}
